package com.bgi.cg.oss4j.core.load;

import com.bgi.cg.api.BaseOssService;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义的一个平滑加权负载服务，可以用于存放多个OSS实现负载
 *
 * @author Z.cg
 */
public class OssLoad {
    // 服务器列表，每个服务器有一个权重和当前权重
    private static final List<LoadServer> LoadServers = new ArrayList<>();

    private OssLoad() {
    }

    /**
     * addLoadServer
     * <p> 添加服务及其权重
     * <p>添加权重应注意，不要把某个权重设置的与其他权重相差过大，否则容易出现无法负载，单一选择的情况
     *
     * @param loadServer 短信实现
     * @param weight     权重
     */
    public static void addLoadServer(BaseOssService loadServer, int weight) {
        LoadServers.add(new LoadServer(loadServer, weight, weight));
    }

    /**
     * removeLoadServer
     * <p>移除短信服务
     *
     * @param loadServer 要移除的服务
     */
    public static void removeLoadServer(BaseOssService loadServer) {
        for (int i = 0; i < LoadServers.size(); i++) {
            if (LoadServers.get(i).getOssServer().equals(loadServer)) {
                LoadServers.remove(i);
                break;
            }
        }
    }

    /**
     * getLoadServer
     * <p>根据负载算法获取一个可获取到的短信服务，这里获取到的服务必然是addLoadServer方法中添加过的服务，不会凭空出现
     *
     * @return BaseOssService OSS 实现
     */
    public static BaseOssService getLoadServer() {
        int totalWeight = 0;
        LoadServer selectedLoadServer = null;
        // 计算所有服务器的权重总和，并选择当前权重最大的服务器
        for (LoadServer LoadServer : LoadServers) {
            totalWeight += LoadServer.getWeight();
            int currentWeight = LoadServer.getCurrentWeight() + LoadServer.getWeight();
            LoadServer.setCurrentWeight(currentWeight);
            if (selectedLoadServer == null || LoadServer.getCurrentWeight() > selectedLoadServer.getCurrentWeight()) {
                selectedLoadServer = LoadServer;
            }
        }
        // 如果没有服务器，则返回空
        if (selectedLoadServer == null) {
            return null;
        }
        // 更新选择的服务器的当前权重，并返回其地址
        int i = selectedLoadServer.getCurrentWeight() - totalWeight;
        selectedLoadServer.setCurrentWeight(i);
        return selectedLoadServer.getOssServer();
    }
}

